#include "node.hh"
#include "constants.hh"
#include "evolution/constants.hh"
#include <cassert>
#include <cmath>
using namespace std;

namespace cppn {
    using evolution::NodeGene;
    using evolution::NodeType;

    Node::Node (NodeGene const& gene) 
    : id(gene.get_id()), type(gene.get_type()), bias(gene.get_weight())
    {
    }

    float
    Node::activation (int t, float state, float bias) {
        NodeType type = NodeType(t);

        switch (type) {
        case NodeType::GAUSSIAN: 
            if (bias == 0) bias = 1.0f;
            return exp(-(state*state)/(bias*bias*(1.0f/64.0f)));

        case NodeType::SINE:
            return sin(state*bias);

        case NodeType::COSINE:
            return cos(state*bias);

        case NodeType::LINEAR: 
            return state*bias;

        case NodeType::SIGMOID:
            return 2.0f/(1.0f + exp(-state + bias)) - 1.0f;

        case NodeType::POW:
            return pow(state + bias/(evolution::WEIGHT_RANGE), 3.0f)
                        / pow(evolution::WEIGHT_RANGE, 3.0f);
        case NodeType::ABS:
            return abs(state + bias);
            
        case NodeType::SIGN:
            return state + bias > 0 ? 1 : -1;

        case NodeType::STAIR:
            return int(state*bias);

        case NodeType::CUTOFF: default:
            return state > bias ? 1.0f : -1.0f;
        }
    }

    void Node::connect_from (Node* src, float weight) {
        inputs.push_back({src, weight});
    }

    void Node::connect_to (Node* dst, float weight) {
        dst->connect_from(this, weight);
    }

    ann::Node const*
    Connection::get_source() const { return src; }
}














